package com.zitangkou.gateway.util;

import com.zitangkou.common.enums.RedisKeyEnum;
import com.zitangkou.common.enums.RespEnum;
import com.zitangkou.common.enums.SecretEnum;
import com.zitangkou.common.global.GlobalException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.util.HashMap;
import java.util.Map;

/**
 * Jwt 工具类
 *
 * @author Deng Ningning
 * @version 1.0
 * @date 2020/8/17 11:58
 */
@Component
public class JwtUtil {

    private final RedisUtil redisUtil;

    @Autowired
    public JwtUtil(RedisUtil redisUtil) {
        this.redisUtil = redisUtil;
    }

    private static final String TOKEN_ENTERPRISE_ID = "enterpriseId";
    private static final String TOKEN_USER_ACCOUNT = "userAccount";
    private static final String TOKEN_CREATE_TIME = "createTime";
    private static final String TOKEN_EXPIRE_TIME = "expireTime";

    /**
     * 生成 token
     *
     * @param enterpriseId
     * @param userAccount
     * @return java.lang.String
     * @author Deng Ningning
     * @date 2020/9/3 22:57
     */
    public String generateToken(String enterpriseId, String userAccount) {
        Map<String, Object> userMap = new HashMap<>(10);
        userMap.put(TOKEN_ENTERPRISE_ID, enterpriseId);
        userMap.put(TOKEN_USER_ACCOUNT, userAccount);
        // 失效时间
        Instant instant = Instant.now();
        userMap.put(TOKEN_CREATE_TIME, instant.getEpochSecond());
        userMap.put(TOKEN_EXPIRE_TIME, instant.plusSeconds(
                RedisKeyEnum.USER_INFO_CODE.getMinutes() * 60L
        ).getEpochSecond());
        // 生成token
        return Jwts.builder()
                .setSubject("user")
                .setClaims(userMap)
                .signWith(SignatureAlgorithm.HS512, SecretEnum.TOKEN_SECRET.getValue())
                .compact();
    }

    /**
     * 验证 token
     *
     * @param token
     * @return java.lang.String
     * @author Deng Ningning
     * @date 2020/9/3 22:57
     */
    public String validateToken(String token) {
        if (StringUtils.isEmpty(token)) {
            throw new GlobalException(RespEnum.TOKEN_IS_NULL);
        }
        Map<String, Object> userMap = Jwts.parser()
                .setSigningKey(SecretEnum.TOKEN_SECRET.getValue())
                .parseClaimsJws(token)
                .getBody();
        // 校验失效
        long expireTime = (Integer) userMap.get(TOKEN_EXPIRE_TIME);
        if (Instant.now().getEpochSecond() > expireTime) {
            throw new GlobalException(RespEnum.TOKEN_EXPIRED);
        }
        // 校验用户信息
        if (null == userMap.get(TOKEN_USER_ACCOUNT)) {
            throw new GlobalException(RespEnum.TOKEN_IS_NULL);
        }
        // 查询用户缓存信息，判断是否失效，用户登出时会清除缓存
        Object enterpriseId = userMap.get(TOKEN_ENTERPRISE_ID);
        String userAccount = (String) userMap.get(TOKEN_USER_ACCOUNT);
        String userInfo = redisUtil.get(String.format(RedisKeyEnum.USER_INFO_CODE.getKey(), enterpriseId, userAccount));
        if (StringUtils.isEmpty(userInfo)) {
            throw new GlobalException(RespEnum.TOKEN_IS_NULL);
        }
        return userInfo;
    }
}
